package models;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NoResultException;
import javax.persistence.OneToMany;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

import play.db.jpa.Model;
import client.dtos.RepositoryFileDTO;
import client.dtos.SearchRequest;

@Entity
@NamedQueries({
@NamedQuery(name="RepositoryFile.findByPath",
			query="from RepositoryFile r where r.path=:path and r.repository=:repository"),
@NamedQuery(name="RepositoryFile.search",
			query="from RepositoryFile r where r.path like :path")
})
public class RepositoryFile extends Model {
	
	@ManyToOne
	public Repository repository;
	
	public String path;
	
	@OneToMany
	public Set<FileRevision> revisions;

	public boolean hidden;

	public static RepositoryFile findOrCreateByPath(
			Repository repositoryToCheck, String key) {
		try {
			return findByPath(repositoryToCheck, key);
		} catch (NoResultException nre) {
			final RepositoryFile rf = new RepositoryFile();
			rf.path=key;
			rf.repository=repositoryToCheck;
			return rf.save();
		}
	}

	private static RepositoryFile findByPath(Repository repositoryToCheck,
			String key) {
		return (RepositoryFile)em().createNamedQuery("RepositoryFile.findByPath")
		    	   				   .setParameter("path", key)
		    	   				   .setParameter("repository", repositoryToCheck)
		    	   				   .getSingleResult();
	}

	public static List<RepositoryFile> findByName(String searchTerm) {
		final Session session = (Session)em().getDelegate();
		return session.createCriteria(RepositoryFile.class)
		              .add(Restrictions.like("path", searchTerm, MatchMode.END))
		              .list();
	}

	public static List<RepositoryFile> findBySearchRequest(final SearchRequest searchRequest) {
		final Session session = (Session)em().getDelegate();
		final Criteria searchCriteria = session.createCriteria(RepositoryFile.class);
		if (searchRequest.getFileName()!=null) {
			searchCriteria.add(Restrictions.like("path", searchRequest.getFileName(), MatchMode.END));
		}
		return searchCriteria.list();
	}
	
	public static List<RepositoryFile> findByPath(final String path, final boolean anywhere) {
		final Session session = (Session)em().getDelegate();
		final Criteria searchCriteria = session.createCriteria(RepositoryFile.class);
		final MatchMode matchMode;
		if (anywhere) {
			matchMode = MatchMode.ANYWHERE;
		} else {
			matchMode = MatchMode.END;
		}
		searchCriteria.add(Restrictions.like("path", path, matchMode));
		searchCriteria.add(Restrictions.eq("hidden", false));
		searchCriteria.setMaxResults(200);
		return searchCriteria.list();
	}
	
	public static List<RepositoryFileDTO> convertToDTOs(final List<RepositoryFile> repositoryFile) {
		final List<RepositoryFileDTO> repositoryFileDTOs = new ArrayList<RepositoryFileDTO>(repositoryFile.size());
		for (final RepositoryFile f : repositoryFile) {
			final RepositoryFileDTO dto = convertToDTO(f);
			repositoryFileDTOs.add(dto);
		}
		return repositoryFileDTOs;
	}

	private static RepositoryFileDTO convertToDTO(RepositoryFile f) {
		final RepositoryFileDTO dto = new RepositoryFileDTO();
		dto.setPath(f.path);
		dto.setRepositoryFileID(f.id);
		return dto;
	}
	
}
